package cevent.source.cloudcenter.source.controller.admin;/**
 * Created by Cevent on 2021/4/30.
 */

import cevent.source.cloudcenter.server.dto.FileDto;
import cevent.source.cloudcenter.server.dto.ResponseDataDto;
import cevent.source.cloudcenter.server.enums.UseTypeEnum;
import cevent.source.cloudcenter.server.service.FileService;
import cevent.source.cloudcenter.server.util.Base64ToMultipartFile;
import cevent.source.cloudcenter.server.util.UUID8Util;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.AppendObjectRequest;
import com.aliyun.oss.model.AppendObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author cevent
 * @description 阿里云OSS上传
 * @date 2021/4/30 9:11
 */
@RestController
@RequestMapping("/admin/oss")
public class OSSController {
    public static final Logger LOG= LoggerFactory.getLogger(OSSController.class);
    public static final String BUSINESS_NAME="阿里云OSS文件上传";

    @Value("${oss.accessKeyID}")
    private String ACCESS_KEY_ID;
    @Value("${oss.accessKeySecret}")
    private String ACCESS_KEY_SECRET;
    @Value("${oss.bucket}")
    private String BUCKET;
    @Value("${oss.endpoint}")
    private String END_POINT;
    @Value("${oss.endpointfieldName}")
    private String END_POINT_FIELD_NAME;

    @Resource
    FileService fileService;
    //1.简单上传
    @PostMapping("/simple")
    public ResponseDataDto uploadSimpleOSS(@RequestParam MultipartFile file,String useType,String moduleId) throws IOException {
        //获取枚举类型，生成新的文件夹路径
        UseTypeEnum useTypeEnum = UseTypeEnum.getByCode(useType);
        String shardKey= UUID8Util.getShortUUID();
        String fileName = file.getOriginalFilename();
        String fileKey = UUID8Util.getShortUUID();
        //获取文件后缀名(类型)，全部转小写
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        String contentType = file.getContentType();
        Long size = file.getSize();

        //文件名配置
        Date now = new Date();
        String date = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(now);
        //获取到枚举名SOURCE("","")
        String dateDir = new SimpleDateFormat("yyyy_MM_dd").format(now);
        String dir = useTypeEnum.name().toLowerCase();
        String name = date + "_" + fileKey + "_" + fileName;
        //File.separator生成不同操作系统的/斜杠
        String path = "source/" + dir + File.separator + dateDir + File.separator + name;
        LOG.info("上传的path：{}", path);

        //保存file
        FileDto fileDto = new FileDto();
        fileDto.setName(name);
        //OSS上传
        OSS ossClient=new OSSClientBuilder().build(END_POINT,ACCESS_KEY_ID,ACCESS_KEY_SECRET);
        PutObjectRequest putObjectRequest=new PutObjectRequest(BUCKET,path,new ByteArrayInputStream(file.getBytes()));
        //上传字符串
        ossClient.putObject(putObjectRequest);
        //fileDto.setPath(path);
        //返回全路径
        fileDto.setPath(path);
        fileDto.setSuffix(suffix);
        fileDto.setContentType(contentType);
        fileDto.setSize(Math.toIntExact(size));
        fileDto.setUseType(useType);
        fileDto.setIsShow(0);
        fileDto.setModuleId(moduleId);

        fileService.save(fileDto);
        ResponseDataDto responseData = new ResponseDataDto();
        responseData.setResponseData(fileDto);
        return responseData;
    }
    //2.追加上传
    @RequestMapping("/append")
    public ResponseDataDto uploadAppendOSS(@RequestBody FileDto fileDto) throws IOException, InterruptedException {

        String useType = fileDto.getUseType();
        //获取枚举类型，生成新的文件夹路径
        UseTypeEnum useTypeEnum = UseTypeEnum.getByCode(useType);
        LOG.info("传入的useType：{}", useType);
        String fileName=fileDto.getName();
        LOG.info("传入的fileName：{}",fileName);
        String name=fileName.substring(0,fileName.lastIndexOf("."));
        LOG.info("截取的name：{}",name);
        String suffix=fileName.substring(fileName.lastIndexOf(".")+1).toLowerCase();
        LOG.info("截取的后缀：{}",suffix);
        fileDto.setName(name+"."+suffix);
        Integer shardIndex=fileDto.getShardIndex();
        Integer shardSize=fileDto.getShardSize();
        String shardBase64 = fileDto.getShard();
        MultipartFile shard = Base64ToMultipartFile.base64TransToMultipartFile(shardBase64);
        Date now = new Date();
        String date = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(now);
        String dateDir = new SimpleDateFormat("yyyy_MM_dd").format(now);
        String dir = useTypeEnum.name().toLowerCase();
        //合并名
        String mergeName = date + "_" + fileDto.getShardKey() + "_" + fileDto.getName();
        /**
         * File.separator生成不同操作系统的/斜杠
         * 更新分片传入，将每个分片文件后缀改为xx.mp4.shardIndex
         * 注意：阿里云OSS文件判断，文件名携带唯一key即可，如果加入时间戳，无法获取到下一次append的文件名
         */
        String path = new StringBuffer("source/")
                .append(dir)
                .append("/").append(dateDir).append("/")
                .append(dateDir).append("_")
                .append(fileDto.getShardKey()).append("_")
                .append(fileDto.getName())
                .toString();//.append(fileKey)
        LOG.info("分片传输--》上传的path：{}", path);

        /**
         * OSS文件上传
         */
        //1.创建OSSClient实例
        OSS OSSClient=new OSSClientBuilder().build(END_POINT,ACCESS_KEY_ID,ACCESS_KEY_SECRET);
        ObjectMetadata metadata=new ObjectMetadata();
        //2.指定上传类型
        metadata.setContentType("text/plain");
        //3.通过AppendObjectRequest设置多个参数
        if(shard != null){
            AppendObjectRequest appendObjectRequest=new AppendObjectRequest(
                    BUCKET,
                    path,
                    new ByteArrayInputStream(shard.getBytes()),
                    metadata);
            //4.追加文件(起始位置，默认为0)：每次请求上传一个分片，这里只需要一次追加
            appendObjectRequest.setPosition((long)((shardIndex-1)*shardSize));
            //5.将拼接的appendObjectRequest放入result
            AppendObjectResult appendObjectResult=OSSClient.appendObject(appendObjectRequest);
            //6.文件的64位CRC值，根据ECMA-182标准计算
            System.out.println(JSONObject.toJSONString(appendObjectResult));
            //7.关闭ossClient
            OSSClient.shutdown();
        }
        //保存file,返回相对路径
        //fileDto.setPath(path);
        //返回全路径
        fileDto.setPath(END_POINT_FIELD_NAME+"/"+path);
        //改用requestBody传参，这里不需要set已经存在在dto中的属性
        fileDto.setName(mergeName);
        fileDto.setIsShow(0);
        //阿里云自动追加拼接合并文件，不需要merge
        fileService.save(fileDto);
        ResponseDataDto responseData = new ResponseDataDto();
        responseData.setResponseData(fileDto);
        return responseData;
    }


}
